package framework.collision;

import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.geom.Rectangle;

import framework.BasicFighter;
import framework.Updatable;

public class FighterCollisionManager implements CollisionManager<BasicFighter>, Updatable {

	ArrayList<BasicFighter> elements;
	
	private int groundHeight;

	public FighterCollisionManager() {
		elements = new ArrayList<BasicFighter>();
		groundHeight = 0;
	}

	@Override
	public void addElement(BasicFighter element) {
		this.elements.add(element);		
	}

	@Override
	public boolean checkCollision(BasicFighter element1, BasicFighter element2) {
		return element1.getHitBox().intersects(element2.getHitBox());
	}

	public static Rectangle2D getCollision(BasicFighter element1, BasicFighter element2) {
		Rectangle r1 = element1.getHitBox();
		Rectangle r2 = element2.getHitBox();
		java.awt.Rectangle rect1 = new java.awt.Rectangle((int)r1.getX(), (int)r1.getY(), (int)r1.getWidth(), (int)r1.getHeight());
		java.awt.Rectangle rect2 = new java.awt.Rectangle((int)r2.getX(), (int)r2.getY(), (int)r2.getWidth(), (int)r2.getHeight());
		return rect1.createIntersection(rect2);
	}

	public void manageCollision(BasicFighter movingElement, BasicFighter element, GameContainer gc) {
		Rectangle2D collision = getCollision(movingElement, element);
		int elementX = (int) element.getHitBox().getX();
		int elementX2 = elementX + (int) element.getHitBox().getWidth();
		float center1 = movingElement.getHitBox().getCenterX();
		float center2 = element.getHitBox().getCenterX();

		if (center1 > center2 && collision.getWidth() > 0) { // both elements are moving or none
			element.setX((int)(element.getX() - collision.getWidth() / 2));
			movingElement.setX((int)(movingElement.getX() + collision.getWidth() / 2));
		} else if (center1 <= center2 && collision.getWidth() > 0) {
			element.setX((int)(element.getX() + collision.getWidth() / 2));
			movingElement.setX((int)(movingElement.getX() - collision.getWidth() / 2));
		} else if (elementX == 0) { // one element collide with boundaries
			movingElement.setX((int)(movingElement.getX() + collision.getWidth()));
		} else if (elementX2 == gc.getWidth()) {
			movingElement.setX((int)(movingElement.getX() - collision.getWidth()));
		} 
	}

	public void manageCollisions(GameContainer gc) {
		for (int i=0; i < this.elements.size(); i++) {
				for (int j=0; j < this.elements.size(); j++) {
					if (i != j && checkCollision(this.elements.get(i), this.elements.get(j))) {
						manageCollision(this.elements.get(i), this.elements.get(j), gc);
					}
				}
		}
	}

	@Override
	public void update(GameContainer gc, int delta) {
		manageBoundaries(gc);
		manageCollisions(gc);
	}

	public void manageBoundaries(GameContainer gc) {
		int offset = 0;
		for (BasicFighter f : this.elements) {
			if(f.getHitBox().getX() < 0) {
				f.setX(- (int) (f.getHitBox().getX() - f.getX()));
			}
			if(f.getHitBox().getX() + f.getHitBox().getWidth() > gc.getWidth()) {
				offset = (int) (f.getHitBox().getX() - f.getX());
				f.setX((int) (gc.getWidth() - f.getHitBox().getWidth() - offset));
			}
			if(f.getY() >= gc.getHeight() - groundHeight - f.getHeight() && f.getYspeed() >= 0) {
				f.setY(gc.getHeight() - groundHeight - (int)f.getHeight());
				f.setYspeed(0);
			}
		}	
	}

	public int getGroundHeight() {
		return groundHeight;
	}

	public void setGroundHeight(int groundHeight) {
		this.groundHeight = groundHeight;
	}
}
